﻿#ifndef SANDBOX_AVX
#define SANDBOX_AVX
#include <cmath>
#include "commands.h"
enum V_OP
{
    VADD,
    VSUB,
    VMUL,
    VDIV,
    VMOD,
    VPOW,
    VLOG,
    V_MUL_ADD,
    V_ADD_MUL
};
void vfunccv(qword code)
{
    byte opcode = (code & 0x0000ff0000000000) >> 36;
    byte target = (code & 0xf000) >> 12;
    byte source1 = (code & 0x0f00) >> 8;
    byte source2 = (code & 0x00f0) >> 4;
    byte source3 = code & 0x0f;
    switch (opcode)
    {
    case VADD:
        for (int i = 0; i < 64; i++)
            vregs[target].bvalues[i] = vregs[source1].bvalues[i] + vregs[source2].bvalues[i];
        break;
    case VSUB:
        for (int i = 0; i < 64; i++)
            vregs[target].bvalues[i] = vregs[source1].bvalues[i] - vregs[source2].bvalues[i];
        break;
    case VMUL:
        for (int i = 0; i < 64; i++)
            vregs[target].bvalues[i] = vregs[source1].bvalues[i] * vregs[source2].bvalues[i];
        break;
    case VDIV:
        for (int i = 0; i < 64; i++)
            vregs[target].bvalues[i] = vregs[source1].bvalues[i] / vregs[source2].bvalues[i];
        break;
    case VMOD:
        for (int i = 0; i < 64; i++)
            vregs[target].bvalues[i] = vregs[source1].bvalues[i] % vregs[source2].bvalues[i];
        break;
    case VPOW:
        for (int i = 0; i < 64; i++)
            vregs[target].bvalues[i] = (byte)pow(vregs[source1].bvalues[i], vregs[source2].bvalues[i]);
        break;
    case VLOG:
        for (int i = 0; i < 64; i++)
            vregs[target].bvalues[i] = (byte)log(vregs[source1].bvalues[i]) / log(vregs[source2].bvalues[i]);
        break;
    case V_MUL_ADD:
        for (int i = 0; i < 64; i++)
            vregs[target].bvalues[i] = vregs[source1].bvalues[i] * vregs[source2].bvalues[i] + vregs[source3].bvalues[i];
        break;
    case V_ADD_MUL:
        for (int i = 0; i < 64; i++)
            vregs[target].bvalues[i] = vregs[source2].bvalues[i] * vregs[source3].bvalues[i] + vregs[source1].bvalues[i];
        break;
    default:
        break;
    }
}
void vfuncsv(qword code)
{
    byte opcode = (code & 0x0000ff0000000000) >> 36;
    byte target = (code & 0xf000) >> 12;
    byte source1 = (code & 0x0f00) >> 8;
    byte source2 = (code & 0x00f0) >> 4;
    byte source3 = code & 0x0f;
    switch (opcode)
    {
    case VADD:
        for (int i = 0; i < 32; i++)
            vregs[target].wvalues[i] = vregs[source1].wvalues[i] + vregs[source2].wvalues[i];
        break;
    case VSUB:
        for (int i = 0; i < 32; i++)
            vregs[target].wvalues[i] = vregs[source1].wvalues[i] - vregs[source2].wvalues[i];
        break;
    case VMUL:
        for (int i = 0; i < 32; i++)
            vregs[target].wvalues[i] = vregs[source1].wvalues[i] * vregs[source2].wvalues[i];
        break;
    case VDIV:
        for (int i = 0; i < 32; i++)
            vregs[target].wvalues[i] = vregs[source1].wvalues[i] / vregs[source2].wvalues[i];
        break;
    case VMOD:
        for (int i = 0; i < 32; i++)
            vregs[target].wvalues[i] = vregs[source1].wvalues[i] % vregs[source2].wvalues[i];
        break;
    case VPOW:
        for (int i = 0; i < 32; i++)
            vregs[target].wvalues[i] = pow(vregs[source1].wvalues[i], vregs[source2].wvalues[i]);
        break;
    case VLOG:
        for (int i = 0; i < 32; i++)
            vregs[target].wvalues[i] = log(vregs[source1].wvalues[i]) / log(vregs[source2].wvalues[i]);
        break;
    case V_MUL_ADD:
        for (int i = 0; i < 32; i++)
            vregs[target].wvalues[i] = vregs[source1].wvalues[i] * vregs[source2].wvalues[i] + vregs[source3].wvalues[i];
        break;
    case V_ADD_MUL:
        for (int i = 0; i < 32; i++)
            vregs[target].wvalues[i] = vregs[source2].wvalues[i] * vregs[source3].wvalues[i] + vregs[source1].wvalues[i];
        break;
    default:
        break;
    }
}
void vfunciv(qword code)
{
    byte opcode = (code & 0x0000ff0000000000) >> 36;
    byte target = (code & 0xf000) >> 12;
    byte source1 = (code & 0x0f00) >> 8;
    byte source2 = (code & 0x00f0) >> 4;
    byte source3 = code & 0x0f;
    switch (opcode)
    {
    case VADD:
        for (int i = 0; i < 16; i++)
            vregs[target].dvalues[i] = vregs[source1].dvalues[i] + vregs[source2].dvalues[i];
        break;
    case VSUB:
        for (int i = 0; i < 16; i++)
            vregs[target].dvalues[i] = vregs[source1].dvalues[i] - vregs[source2].dvalues[i];
        break;
    case VMUL:
        for (int i = 0; i < 16; i++)
            vregs[target].dvalues[i] = vregs[source1].dvalues[i] * vregs[source2].dvalues[i];
        break;
    case VDIV:
        for (int i = 0; i < 16; i++)
            vregs[target].dvalues[i] = vregs[source1].dvalues[i] / vregs[source2].dvalues[i];
        break;
    case VMOD:
        for (int i = 0; i < 16; i++)
            vregs[target].dvalues[i] = vregs[source1].dvalues[i] % vregs[source2].dvalues[i];
        break;
    case VPOW:
        for (int i = 0; i < 16; i++)
            vregs[target].dvalues[i] = pow(vregs[source1].dvalues[i], vregs[source2].dvalues[i]);
        break;
    case VLOG:
        for (int i = 0; i < 16; i++)
            vregs[target].dvalues[i] = log(vregs[source1].dvalues[i]) / log(vregs[source2].dvalues[i]);
        break;
    case V_MUL_ADD:
        for (int i = 0; i < 16; i++)
            vregs[target].dvalues[i] = vregs[source1].dvalues[i] * vregs[source2].dvalues[i] + vregs[source3].dvalues[i];
        break;
    case V_ADD_MUL:
        for (int i = 0; i < 16; i++)
            vregs[target].dvalues[i] = vregs[source2].dvalues[i] * vregs[source3].dvalues[i] + vregs[source1].dvalues[i];
        break;
    default:
        break;
    }
}
void vfunclv(qword code)
{
    byte opcode = (code & 0x0000ff0000000000) >> 36;
    byte target = (code & 0xf000) >> 12;
    byte source1 = (code & 0x0f00) >> 8;
    byte source2 = (code & 0x00f0) >> 4;
    byte source3 = code & 0x0f;
    switch (opcode)
    {
    case VADD:
        for (int i = 0; i < 8; i++)
            vregs[target].qvalues[i] = vregs[source1].qvalues[i] + vregs[source2].qvalues[i];
        break;
    case VSUB:
        for (int i = 0; i < 8; i++)
            vregs[target].qvalues[i] = vregs[source1].qvalues[i] - vregs[source2].qvalues[i];
        break;
    case VMUL:
        for (int i = 0; i < 8; i++)
            vregs[target].qvalues[i] = vregs[source1].qvalues[i] * vregs[source2].qvalues[i];
        break;
    case VDIV:
        for (int i = 0; i < 8; i++)
            vregs[target].qvalues[i] = vregs[source1].qvalues[i] / vregs[source2].qvalues[i];
        break;
    case VMOD:
        for (int i = 0; i < 8; i++)
            vregs[target].qvalues[i] = vregs[source1].qvalues[i] % vregs[source2].qvalues[i];
        break;
    case VPOW:
        for (int i = 0; i < 8; i++)
            vregs[target].qvalues[i] = pow(vregs[source1].qvalues[i], vregs[source2].qvalues[i]);
        break;
    case VLOG:
        for (int i = 0; i < 8; i++)
            vregs[target].qvalues[i] = log(vregs[source1].qvalues[i]) / log(vregs[source2].qvalues[i]);
        break;
    case V_MUL_ADD:
        for (int i = 0; i < 8; i++)
            vregs[target].qvalues[i] = vregs[source1].qvalues[i] * vregs[source2].qvalues[i] + vregs[source3].qvalues[i];
        break;
    case V_ADD_MUL:
        for (int i = 0; i < 8; i++)
            vregs[target].qvalues[i] = vregs[source2].qvalues[i] * vregs[source3].qvalues[i] + vregs[source1].qvalues[i];
        break;
    default:
        break;
    }
}
void vfuncfv(qword code)
{
    byte opcode = (code & 0x0000ff0000000000) >> 36;
    byte target = (code & 0xf000) >> 12;
    byte source1 = (code & 0x0f00) >> 8;
    byte source2 = (code & 0x00f0) >> 4;
    byte source3 = code & 0x0f;
    switch (opcode)
    {
    case VADD:
        for (int i = 0; i < 16; i++)
            vregs[target].r4values[i] = vregs[source1].r4values[i] + vregs[source2].r4values[i];
        break;
    case VSUB:
        for (int i = 0; i < 16; i++)
            vregs[target].r4values[i] = vregs[source1].r4values[i] - vregs[source2].r4values[i];
        break;
    case VMUL:
        for (int i = 0; i < 16; i++)
            vregs[target].r4values[i] = vregs[source1].r4values[i] * vregs[source2].r4values[i];
        break;
    case VDIV:
        for (int i = 0; i < 16; i++)
            vregs[target].r4values[i] = vregs[source1].r4values[i] / vregs[source2].r4values[i];
        break;
    case VPOW:
        for (int i = 0; i < 16; i++)
            vregs[target].r4values[i] = pow(vregs[source1].r4values[i], vregs[source2].r4values[i]);
        break;
    case VLOG:
        for (int i = 0; i < 16; i++)
            vregs[target].r4values[i] = log(vregs[source1].r4values[i]) / log(vregs[source2].r4values[i]);
        break;
    case V_MUL_ADD:
        for (int i = 0; i < 16; i++)
            vregs[target].r4values[i] = vregs[source1].r4values[i] * vregs[source2].r4values[i] + vregs[source3].r4values[i];
        break;
    case V_ADD_MUL:
        for (int i = 0; i < 16; i++)
            vregs[target].r4values[i] = vregs[source2].r4values[i] * vregs[source3].r4values[i] + vregs[source1].r4values[i];
        break;
    default:
        break;
    }
}
void vfuncdv(qword code)
{
    byte opcode = (code & 0x0000ff0000000000) >> 36;
    byte target = (code & 0xf000) >> 12;
    byte source1 = (code & 0x0f00) >> 8;
    byte source2 = (code & 0x00f0) >> 4;
    byte source3 = code & 0x0f;
    switch (opcode)
    {
    case VADD:
        for (int i = 0; i < 8; i++)
            vregs[target].r8values[i] = vregs[source1].r8values[i] + vregs[source2].r8values[i];
        break;
    case VSUB:
        for (int i = 0; i < 8; i++)
            vregs[target].r8values[i] = vregs[source1].r8values[i] - vregs[source2].r8values[i];
        break;
    case VMUL:
        for (int i = 0; i < 8; i++)
            vregs[target].r8values[i] = vregs[source1].r8values[i] * vregs[source2].r8values[i];
        break;
    case VDIV:
        for (int i = 0; i < 8; i++)
            vregs[target].r8values[i] = vregs[source1].r8values[i] / vregs[source2].r8values[i];
        break;
    case VPOW:
        for (int i = 0; i < 8; i++)
            vregs[target].r8values[i] = pow(vregs[source1].r8values[i], vregs[source2].r8values[i]);
        break;
    case VLOG:
        for (int i = 0; i < 8; i++)
            vregs[target].r8values[i] = log(vregs[source1].r8values[i]) / log(vregs[source2].r8values[i]);
        break;
    case V_MUL_ADD:
        for (int i = 0; i < 8; i++)
            vregs[target].r8values[i] = vregs[source1].r8values[i] * vregs[source2].r8values[i] + vregs[source3].r8values[i];
        break;
    case V_ADD_MUL:
        for (int i = 0; i < 8; i++)
            vregs[target].r8values[i] = vregs[source2].r8values[i] * vregs[source3].r8values[i] + vregs[source1].r8values[i];
        break;
    default:
        break;
    }
}
void vload(qword code)
{
    byte target = (code & 0x0000f00000000000) >> 44;
    byte length = (code & 0x00000f0000000000) >> 40;
    byte base = (code & 0x0000000700000000) >> 32;
    dword address = code & 0xffffffff;
    strncpy((char *)(vregs[target].bvalues), (char *)(ram + addr_regs[base] + address), length);
}
void vstore(qword code)
{
    byte target = (code & 0x0000f00000000000) >> 44;
    byte length = (code & 0x00000f0000000000) >> 40;
    byte base = (code & 0x0000000700000000) >> 32;
    dword address = code & 0xffffffff;
    strncpy((char *)(ram + addr_regs[base] + address), (char *)(vregs[target].bvalues), length);
}
void vpush(qword code)
{
    byte target = code & 0x0f;
    strncpy((char *)(ram + addr_regs[Stack] - 64), (char *)(vregs + target), 64);
    addr_regs[Stack] -= 64;
}
void vpop(qword code)
{
    byte target = code & 0x0f;
    strncpy((char *)(vregs + target), (char *)(ram + addr_regs[Stack]), 64);
    addr_regs[Stack] += 64;
}

#endif
